#pragma once
#include<iostream>
#include<string>
#include<cstdio>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdalign.h>
#include<unistd.h>

const std::string gpath = "/home/myq/linux/";
int gprojId = 0x6666;
//操作系统申请空间, 是按照块为单位的:4KB, 1KB, 2KB, 4MB
//但是只能用自己申请空间

int gshmsize = 4096;
mode_t gmode = 0600; //权限

//打印系统生成的key
std::string ToHex(key_t k)
{
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "0x%x", k);
    return buffer;
}


class ShareMemory
{
    //创建共享内存
private:
    void CreateShmHelper(int shmflg)
    {
        _key = ::ftok(gpath.c_str(), gprojId);
        if(_key < 0) //因为默认生成的都是大于0的
        {
            std::cerr << "ftok error" << std::endl;
            return ;
        }
        //获取贡献内存, 创建共享内存
        _shmid = ::shmget(_key, gshmsize, shmflg);
        if(_shmid < 0)
        {
            std::cerr << "shmget error" <<std::endl;
            return ;
        }
        std::cout << "shmid : " << _shmid << std::endl; 
    }
public:
    ShareMemory()
    : _shmid(-1),
      _key(0),
      _addr(nullptr)
      {}
    ~ShareMemory() {}
    //创建一个新的共享内存
    void CreateShm()
    {
        if(_shmid == -1)
            CreateShmHelper(IPC_CREAT | IPC_EXCL | gmode);
        std::cout << "key" << ToHex(_key) << std::endl;
    }
    //获取共享进程
    void GetShm()
    {
        CreateShmHelper(IPC_CREAT);
    }
    //挂载到虚拟内存
    void AttchShm()
    {
        _addr = shmat(_shmid, nullptr, 0);
        if((long long)_addr == -1)
        {
            std::cout << "attach error" << std::endl;
        }
    }
    //移除挂载
    void DetachShm()
    {
        if(_addr != nullptr)
            ::shmdt(_addr);
        std::cout << "detach done: " << std::endl; 
    }
    //删除共享内存
    void DeleteShm()
    {
        shmctl(_shmid, IPC_RMID, nullptr);
    }
    //获取系统挂载后的虚拟地址
    void *GetAddr()
    {
        return _addr;
    }
    void ShmMeta()
    {

    }
private:
    int _shmid; //共享标识符, 对用户
    key_t _key; //key值, 对内核
    void* _addr; //挂载成功的虚拟地址
};
//全局的共享内存
ShareMemory shm;

//数据
struct data
{
    char status[32];
    char lasttime[48];
    char image[4000];
};
